<template>
    <component :is="tag" v-if="show" 
    v-model="data" :label="attrs.ParamCN||''" v-bind="attrs.Control.Bind||{}"/>
</template>
<script setup lang="ts">
import {computed,watch,onUnmounted,customRef  } from 'vue'
import component from './components'
import {CustomCompProps} from './types'
const {attrs,config} = defineProps<CustomCompProps>()

const tag = computed(()=>{
    return attrs.Control.Type&&component[attrs.Control.Type]||attrs.Control.component;
})

const proxy = (()=>{
    if(attrs.ProxyValue){
        let e = attrs.ProxyValue;
        return customRef((track, trigger) => {
            return {
                get() {
                    track()
                    return e.key?parse(e.object, e.key):e.object;
                },
                set(val) {
                    if(e.key){
                        parse(e.object, e.key, val);
                    }
                    else e.object=val;
                    trigger()
                }
            }
        })
    }
})()
/**当前组件的属性值*/
const data = proxy??computed({
    get:()=>config[attrs.Param],
    set:(val)=>config[attrs.Param] = val
})
//联动控制显示隐藏
const show = computed(()=>{
    /**当前控件是否显示 */
    let display = true;
    /**控件联动【控制控件显示隐藏】 */
    let link = attrs.Control.LinkControl;
    if(link){
        display = link.Default
        if(link.Param){
            let value = config[link.Param];
            if(value){
                for(let i=0;i<link.StateCondition.length;i++){
                    let item = link.StateCondition[i];
                    if(item.ConditionType==='Control'){
                        if(item.Condition==='=='){
                            if(value===item.Value)display = item.Display;
                        }
                        else if(item.Condition==='!='){}
                    }
                }
            }
        }
    }
    if(display){
        let defaultValue;
        if(typeof attrs.Value=='object'){
            defaultValue = JSON.parse(JSON.stringify(attrs.Value))
        }else defaultValue = attrs.Value;
        //如果是代理对象，则把参数配置的初始值设置成代理对象的值
        if(attrs.ProxyValue){
            //data.value无值并且配置了默认值时，data.value设置默认值
            data.value ?? ((defaultValue!=null)&&(data.value = defaultValue));
            // 代理对象有值，参数配置无值时，则把代理对象的值赋给参数配置
            (data.value != null)&&(config[attrs.Param]=data.value);
        }
        // 无值的时候赋默认值
        else if(!(attrs.Param in config)){
            if('Value' in attrs)data.value = defaultValue;
        }
    }
    //联动隐藏时删除参数
    else if(!attrs.retainValueOnHide){
        if(attrs.ProxyValue){
            // delete attrs.ProxyValue.object[attrs.ProxyValue.key];
            if(!attrs.ProxyValue.ref&&attrs.ProxyValue.key)parse(attrs.ProxyValue.object,attrs.ProxyValue.key,'',true)
        }
        delete config[attrs.Param]
    }
    return display;
})
//如果有代理对象，使代理对象的值同步参数配置的值
if(attrs.ProxyValue){
    let proxy = attrs.ProxyValue;
    
    if(proxy.key){
        watch(()=>proxy.object[proxy.key!],(val)=>{
            if(config[attrs.Param]!==val)config[attrs.Param] = val;
        })
    }
    else if(proxy.ref){
        watch(()=>proxy.object,(val)=>{
            if(config[attrs.Param]!==val)config[attrs.Param] = val;
        })
    }
    watch(()=>config[attrs.Param],(val)=>{
        if(proxy.ref){
            if(proxy.object!==val&&show.value){
                proxy.object = val;
            }
        }
        else if(proxy.key){
            if(proxy.object[proxy.key]!==val&&show.value){
                proxy.object[proxy.key] = val;
            }
        }
    })
}
onUnmounted(()=>{
    config[attrs.Param] ?? delete config[attrs.Param];
    if(config[attrs.Param]==='')delete config[attrs.Param]
})
/**
 *  解析代理对象
 * @param obj   对象
 * @param key   属性名称
 * @param setData   设置值
 */
function parse(obj: any, key: string, setData?: any,del?:boolean) {
    let str = key.split('.');
    let shift = str.splice(0, 1);

    // args[0] 是当前对象，args[1] 是后续路径
    let target = obj[shift[0]]; // 获取对象的第一层
    let targetKey = str.join('.');

    // 如果传递了 setData 参数，执行赋值操作
    if (arguments.length === 3) {
        if (str.length === 0) {
            // 递归到底，直接设置目标值
            obj[shift[0]] = setData;
        } else {
            // 递归赋值
            // 继续调用 parse，传递子对象与剩余路径
            parse(target, targetKey, setData);
        }
    }
    if(del&&str.length === 0){
        delete obj[shift[0]];
    }

    // 如果还有路径，则递归继续处理
    return str.length ? parse(target, targetKey) : obj[shift[0]];
}
</script>